#include "../../include/core/BankAccount.h"

#include <stdexcept>
#include <limits>

namespace MiniBanking
{

    // --- Constructor ---
    BankAccount::BankAccount(std::string accountID, std::string ownerName, double initialBalance)
        : accountID_(std::move(accountID)),
          ownerName_(std::move(ownerName)),
          balance_(initialBalance)
    {
        if (initialBalance < 0.0)
        {
            throw std::invalid_argument("Initial balance cannot be negative.");
        }
        if (accountID_.empty())
        {
            throw std::invalid_argument("Account ID cannot be empty.");
        }
        if (ownerName_.empty())
        {
            throw std::invalid_argument("Owner name cannot be empty.");
        }
    }

    // --- Getters ---
    const std::string &BankAccount::getAccountID() const
    {
        return accountID_;
    }

    const std::string &BankAccount::getOwnerName() const
    {
        return ownerName_;
    }

    double BankAccount::getBalance() const
    {
        return balance_;
    }

    // --- Protected Balance Modifiers ---
    bool BankAccount::decreaseBalance(double amount)
    {
        if (amount <= 0.0)
        {
            return false; // Cannot decrease by non-positive amount
        }
        if (balance_ >= amount)
        {
            balance_ -= amount;
            return true; // Success
        }
        return false; // Insufficient funds
    }

    void BankAccount::increaseBalance(double amount)
    {
        if (amount <= 0.0)
        {
            return; // Cannot increase by non-positive amount
        }

        balance_ += amount;
    }

    // --- Default Virtual Implementations ---
    bool BankAccount::deposit(double amount)
    {
        // Default: Accounts cannot be deposited into unless overridden
        return false;
    }

    bool BankAccount::withdraw(double amount)
    {
        // Default: Accounts cannot be withdrawn from unless overridden
        return false;
    }

    bool BankAccount::initiateTransferOut(double amount)
    {
        // Base implementation only handles the balance decrease after checks
        // Derived classes MUST call their canTransferTo logic before calling this or reimplementing fully.
        // This method focuses on the "OUT" part: checking funds and decreasing balance.
        return decreaseBalance(amount); // Returns true if funds were sufficient and balance decreased
    }

    bool BankAccount::receiveTransfer(double amount)
    {
        if (amount <= 0.0)
        {
            return false; // Cannot receive non-positive amount
        }
        increaseBalance(amount); // Use the protected method to increase balance
        return true;
    }

}
